home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / archx < prev    next >
Encoding:
Internet Message Format  |  1986-11-30  |  18.4 KB

  1. From: genrad!decvax!decwrl!dec-rhea!dec-pauper!minow  (Martin Minow)
  2. Subject: archx: suggested replacement for shar
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 80
  7. Submitted by: decvax!decwrl!dec-rhea!dec-pauper!minow  (Martin Minow)
  8.  
  9. [
  10.   This is one of two submissions of programs that provide alternatives to
  11.   "shar" as a source archive format.  This does not imply my support of
  12.   one format over another.  Oh, I am distributing these in "shar" format
  13.   to avoid the chicken-or-egg problem.
  14.     - John Nelson - moderator, mod.sources
  15. ]
  16. #! /bin/sh
  17. # This is a shell archive, meaning:
  18. # 1. Remove everything above the #! /bin/sh line.
  19. # 2. Save the resulting text in a file.
  20. # 3. Execute the file with /bin/sh (not csh) to create the files:
  21. #    readme.txt
  22. #    archc.c
  23. #    archx.c
  24. # This archive created: Thu May  1 08:33:31 1986
  25. export PATH; PATH=/bin:$PATH
  26. echo shar: extracting "'readme.txt'" '(1420 characters)'
  27. if test -f 'readme.txt'
  28. then
  29.     echo shar: will not over-write existing file "'readme.txt'"
  30. else
  31. cat << \SHAR_EOF > 'readme.txt'
  32. This is a suggested replacement for shar.  It is based on
  33. the archive program in Kernighan and Plauger's Software Tools,
  34. but has been heavily simplified.
  35.  
  36. It has the following advantages over shar:
  37.  
  38. 1. it is not tied to Unix -- thus VMS users can unpack files without
  39.    excessive effort.  Archc and archx should run without change on
  40.    all Unix and Unix lookalike systems, as well as on VMS (VaxC)
  41.    and all PDP-11 Decus C systems.  It has been in use for over 6
  42.    years.
  43.  
  44. 2. it does not execute the distributed image, but interprets it.  This
  45.    means that trojan horses cannot be concealed in distributions.
  46.  
  47. 3  The distribution file can be edited without damaging the archive.
  48.    (Also, embedded archives can be handled).
  49.  
  50. It has the following disadvantages:
  51.  
  52. 1. It is not as flexible as shar -- it cannot create directories or
  53.    access any other Unix system services.
  54.  
  55. 2. There is no checksum capability (it appears impossible to implement
  56.    checksumming in a system-independent manner).
  57.  
  58. To use, save this message.  Then, use your favorite editor to extract
  59. archx.c (delimited by lines beginning with "-h-" in column 1).  Then
  60. compile archx and run it using the command:
  61.     archx <this_file>
  62. It should produce readme.txt, archx.c, and archc.c.
  63. Manual pages can be produced by extracting the text delimited by
  64.     #ifdef DOCUMENTATION
  65.     ...
  66.     #endif
  67.  
  68. Please report problems to the author:
  69.  
  70. Martin Minow
  71. decvax!minow
  72.  
  73. SHAR_EOF
  74. if test 1420 -ne "`wc -c < 'readme.txt'`"
  75. then
  76.     echo shar: error transmitting "'readme.txt'" '(should have been 1420 characters)'
  77. fi
  78. fi
  79. echo shar: extracting "'archc.c'" '(7759 characters)'
  80. if test -f 'archc.c'
  81. then
  82.     echo shar: will not over-write existing file "'archc.c'"
  83. else
  84. cat << \SHAR_EOF > 'archc.c'
  85. /*
  86.  *            A R C H I V E
  87.  *
  88.  * Create an archive
  89.  *
  90.  */
  91.  
  92. /*)BUILD    $(TKBOPTIONS) = {
  93.             TASK    = ...ARC
  94.         }
  95. */
  96.  
  97. #ifdef    DOCUMENTATION
  98.  
  99. title    archc    text file archive creation
  100. index        text file archive creation
  101.  
  102. synopsis
  103.  
  104.     archc file[s] >archive
  105.  
  106. description
  107.  
  108.     Archc manages archives (libraries) of source files, allowing
  109.     a large number of small files to be stored without using
  110.     excessive system resources.  It copies the set of named
  111.     files to standard output in archive format.
  112.  
  113.     The archx program will recreate the files from an archive.
  114.  
  115.     Note: there are no checks against the same file appearing
  116.     twice in an archive.
  117.  
  118. archive file format
  119.  
  120.     Archive files are standard text files.  Each archive element is
  121.     preceeded by a line of the format:
  122.     .s.nf
  123.     -h-    file.name    date    true_path_name
  124.     .s.f
  125.     Note that there is no line or byte count.  To prevent problems,
  126.     a '-' at the beginning of a record within a user file or embedded
  127.     archive will be "quoted" by doubling it.  The date and true filename
  128.     fields are ignored.  On Dec operating systems, file.name is
  129.     forced to lowercase.  Certain bytes at the beginning of a record are
  130.     also prefixed by '-' to prevent mailers from treating them
  131.     as commands.
  132.  
  133. diagnostics
  134.  
  135.     Diagnostic messages should be self-explanatory
  136.  
  137. author
  138.  
  139.     Martin Minow
  140.  
  141. #endif
  142.  
  143. #include    <stdio.h>
  144. #include    <ctype.h>
  145. #ifdef vms
  146. #include        <ssdef.h>
  147. #include        <stsdef.h>
  148. #define    IO_SUCCESS    (SS$_NORMAL | STS$M_INHIB_MSG)
  149. #define    IO_ERROR    SS$_ABORT
  150. #endif
  151. /*
  152.  * Note: IO_SUCCESS and IO_ERROR are defined in the Decus C stdio.h file
  153.  */
  154. #ifndef    IO_SUCCESS
  155. #define    IO_SUCCESS    0
  156. #endif
  157. #ifndef    IO_ERROR
  158. #define    IO_ERROR    1
  159. #endif
  160. #define EOS        0
  161. #define    FALSE        0
  162. #define    TRUE        1
  163.  
  164. char        text[513];        /* Working text            */
  165. char        name[81];        /* Current archive member name    */
  166. char        pathname[81];        /* Output for argetname()    */
  167. char        *timetext;        /* Time of day text        */
  168. int        verbose        = TRUE; /* TRUE for verbosity        */
  169. FILE        *infd;            /* Input file            */
  170.  
  171. main(argc, argv)
  172. int        argc;            /* Arg count            */
  173. char        *argv[];        /* Arg vector            */
  174. {
  175.     register int        i;    /* Random counter        */
  176.     register char        *fn;    /* File name pointer        */
  177.     register char        *argp;    /* Arg pointer            */
  178.     int            nfiles;
  179.     extern char        *ctime();
  180.     extern long        time();
  181.     long            timval;
  182.  
  183.     time(&timval);
  184.     timetext = ctime(&timval);
  185.     timetext[24] = EOS;
  186. #ifdef vms
  187.     argc = getredirection(argc, argv);
  188. #endif
  189.     if (argc <= 1)
  190.         fprintf(stderr, "No files to archive?\n");
  191. #ifdef    unix
  192.     for (i = 1; i < argc; i++) {
  193.         if ((infd = fopen(argv[i], "r")) == NULL)
  194.         perror(argv[i]);
  195.         else {
  196.         strcpy(pathname, argv[i]);
  197.         import();
  198.         fclose(infd);
  199.         }
  200.     }
  201. #else
  202.     /*
  203.      * Decus C supports fwild/fnext for explicit processing
  204.      * of wild-card filenames.
  205.      */
  206.     for (i = 1; i < argc; i++) {
  207.         if ((infd = fwild(argv[i], "r")) == NULL)
  208.         perror(argv[i]);
  209.         else {
  210.         for (nfiles = 0; fnext(infd) != NULL; nfiles++) {
  211.             fgetname(infd, pathname);
  212.             import();
  213.         }
  214.         fclose(infd);
  215.         if (nfiles == 0)
  216.             fprintf(stderr, "No files match \"%s\"\n", argv[i]);
  217.         }
  218.     }
  219. #endif
  220. }
  221.  
  222. import()
  223. /*
  224.  * Add the file open on infd (with file name in pathname) to
  225.  * the archive.
  226.  */
  227. {
  228.     unsigned int    nrecords;
  229.  
  230.     fixname();
  231.     nrecords = 0;
  232.     printf("-h- %s\t%s\t%s\n", name, timetext, pathname);
  233.     while (fgets(text, sizeof text, infd) != NULL) {
  234.         switch (text[0]) {
  235.         case '-':
  236.         case '.':
  237.         case '~':
  238.         putchar('-');                /* Quote    */
  239.         }
  240.         fputs(text, stdout);
  241.         nrecords++;
  242.     }
  243.     if (ferror(infd)) {
  244.         perror(name);
  245.         fprintf(stderr, "Error when importing a file\n");
  246.     }
  247.     if (verbose) {
  248.         fprintf(stderr, "%u records read from %s\n",
  249.         nrecords, pathname);
  250.     }
  251. }
  252.  
  253. fixname()
  254. /*
  255.  * Get file name (in pathname), stripping off device:[directory]
  256.  * and ;version.  The archive name ("file.ext") is written to name[].
  257.  * On a dec operating system, name is forced to lowercase.
  258.  */
  259. {
  260.     register char    *tp;
  261.     register char    *ip;
  262.     char        bracket;
  263.     extern char    *strrchr();
  264.  
  265. #ifdef    unix
  266.     /*
  267.      * name is after all directory information
  268.      */
  269.     if ((tp = strrchr(pathname, '/')) != NULL)
  270.         tp++;
  271.     else
  272.         tp = pathname;
  273.     strcpy(name, tp);
  274. #else
  275.     strcpy(name, pathname);
  276.     if ((tp = strrchr(name, ';')) != NULL)
  277.         *tp = EOS;
  278.     while ((tp = strchr(name, ':')) != NULL)
  279.         strcpy(name, tp + 1);
  280.     switch (name[0]) {
  281.     case '[':    bracket = ']';
  282.             break;
  283.     case '<':    bracket = '>';
  284.             break;
  285.     case '(':    bracket = ')';
  286.             break;
  287.     default:    bracket = EOS;
  288.             break;
  289.     }
  290.     if (bracket != EOS) {
  291.         if ((tp = strchr(name, bracket)) == NULL) {
  292.         fprintf(stderr, "? Illegal file name \"%s\"\n",
  293.             pathname);
  294.         }
  295.         else {
  296.         strcpy(name, tp + 1);
  297.         }
  298.     }
  299.     for (tp = name; *tp != EOS; tp++) {
  300.         if (isupper(*tp))
  301.         *tp = tolower(*tp);
  302.     }
  303. #endif
  304. }
  305.  
  306. #ifdef    unix
  307. char *
  308. strrchr(stng, chr)
  309. register char    *stng;
  310. register char    chr;
  311. /*
  312.  * Return rightmost instance of chr in stng.
  313.  * This has the wrong name on some Unix systems.
  314.  */
  315. {
  316.     register char    *result;
  317.  
  318.     result = NULL;
  319.  
  320.     do {
  321.         if (*stng == chr)
  322.         result = stng;
  323.     } while (*stng++ != EOS);
  324.     return (result);
  325. }
  326. #endif
  327.  
  328. /*
  329.  * getredirection() is intended to aid in porting C programs
  330.  * to VMS (Vax-11 C) which does not support '>' and '<'
  331.  * I/O redirection.  With suitable modification, it may
  332.  * useful for other portability problems as well.
  333.  */
  334.  
  335. static int
  336. getredirection(argc, argv)
  337. int        argc;
  338. char        **argv;
  339. /*
  340.  * Process vms redirection arg's.  Exit if any error is seen.
  341.  * If getredirection() processes an argument, it is erased
  342.  * from the vector.  getredirection() returns a new argc value.
  343.  *
  344.  * Warning: do not try to simplify the code for vms.  The code
  345.  * presupposes that getredirection() is called before any data is
  346.  * read from stdin or written to stdout.
  347.  *
  348.  * Normal usage is as follows:
  349.  *
  350.  *    main(argc, argv)
  351.  *    int        argc;
  352.  *    char        *argv[];
  353.  *    {
  354.  *        argc = getredirection(argc, argv);
  355.  *    }
  356.  */
  357. {
  358. #ifdef    vms
  359.     register char        *ap;    /* Argument pointer    */
  360.     int            i;    /* argv[] index        */
  361.     int            j;    /* Output index        */
  362.     int            file;    /* File_descriptor     */
  363.  
  364.     for (j = i = 1; i < argc; i++) {   /* Do all arguments    */
  365.         switch (*(ap = argv[i])) {
  366.         case '<':            /* <file        */
  367.         if (freopen(++ap, "r", stdin) == NULL) {
  368.             perror(ap);        /* Can't find file    */
  369.             exit(IO_ERROR);    /* Is a fatal error    */
  370.         }
  371.  
  372.         case '>':            /* >file or >>file    */
  373.         if (*++ap == '>') {    /* >>file        */
  374.             /*
  375.              * If the file exists, and is writable by us,
  376.              * call freopen to append to the file (using the
  377.              * file's current attributes).  Otherwise, create
  378.              * a new file with "vanilla" attributes as if
  379.              * the argument was given as ">filename".
  380.              * access(name, 2) is TRUE if we can write on
  381.              * the specified file.
  382.              */
  383.             if (access(++ap, 2) == 0) {
  384.             if (freopen(ap, "a", stdout) != NULL)
  385.                 break;    /* Exit case statement    */
  386.             perror(ap);    /* Error, can't append    */
  387.             exit(IO_ERROR);    /* After access test    */
  388.             }            /* If file accessable    */
  389.         }
  390.         /*
  391.          * On vms, we want to create the file using "standard"
  392.          * record attributes.  create(...) creates the file
  393.          * using the caller's default protection mask and
  394.          * "variable length, implied carriage return"
  395.          * attributes. dup2() associates the file with stdout.
  396.          */
  397.         if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
  398.          || dup2(file, fileno(stdout)) == -1) {
  399.             perror(ap);        /* Can't create file    */
  400.             exit(IO_ERROR);    /* is a fatal error    */
  401.         }            /* If '>' creation    */
  402.         break;            /* Exit case test    */
  403.  
  404.         default:
  405.         argv[j++] = ap;        /* Not a redirector    */
  406.         break;            /* Exit case test    */
  407.         }
  408.     }                /* For all arguments    */
  409.     return (j);
  410. #else
  411.     /*
  412.      * Note: argv[] is referenced to fool the Decus C
  413.      * syntax analyser, supressing an unneeded warning
  414.      * message.
  415.      */
  416.     return (argv[0], argc);        /* Just return as seen    */
  417. #endif
  418. }
  419.  
  420.  
  421.  
  422. SHAR_EOF
  423. if test 7759 -ne "`wc -c < 'archc.c'`"
  424. then
  425.     echo shar: error transmitting "'archc.c'" '(should have been 7759 characters)'
  426. fi
  427. fi
  428. echo shar: extracting "'archx.c'" '(7837 characters)'
  429. if test -f 'archx.c'
  430. then
  431.     echo shar: will not over-write existing file "'archx.c'"
  432. else
  433. cat << \SHAR_EOF > 'archx.c'
  434. /*
  435.  *            A R C H X
  436.  *
  437.  * Archive extraction
  438.  *
  439.  */
  440.  
  441. /*
  442.  * Note: the )BUILD comment is extracted by a Decus C tool to construct
  443.  * system-dependent compiler command lines.
  444.  *
  445.  * Text inside #ifdef DOCUMENTATION is converted to runoff by a
  446.  * Decus C tool.
  447.  */
  448.  
  449. /*)BUILD    $(TKBOPTIONS) = {
  450.             TASK    = ...ARX
  451.         }
  452. */
  453.  
  454. #ifdef    DOCUMENTATION
  455.  
  456. title    archx    text file archiver extraction
  457. index        text file archiver extraction
  458.  
  459. synopsis
  460.  
  461.     archx archive_files
  462.  
  463. description
  464.  
  465.     Archx manages archives (libraries) of source files, allowing
  466.     a large number of small files to be stored without using
  467.     excessive system resources.  Archx extracts all files from
  468.     an archive.
  469.  
  470.     If no archive_name file is given, the standard input is read.
  471.     Archive header records are echoed to the standard output.
  472.  
  473. archive file format
  474.  
  475.     Archive files are standard text files.  Each archive element is
  476.     preceeded by a line of the format:
  477.     .s.nf
  478.     -h-    file.name    date    true_name
  479.     .s.f
  480.     Note that there is no line or byte count.  To prevent problems,
  481.     a '-' at the beginning of a record within a user file or embedded
  482.     archive will be "quoted" by doubling it.  The date and true filename
  483.     fields are ignored.  On some operating systems, file.name is
  484.     forced to lowercase.  The archive builder (archc) may prefix
  485.     other characters by '-'.
  486.  
  487.     If the first non-blank line of an input file does not
  488.     begin with "-h", the text will be appended to "archx.tmp"
  489.     This is needed if archives are distributed by mail
  490.     and arrive with initial routing and subject information.
  491.  
  492. diagnostics
  493.  
  494.     Diagnostic messages should be self-explanatory
  495.  
  496. author
  497.  
  498.     Martin Minow
  499.  
  500. bugs
  501.  
  502. #endif
  503.  
  504. #include    <stdio.h>
  505. #include    <ctype.h>
  506. #ifdef vms
  507. #include        <ssdef.h>
  508. #include        <stsdef.h>
  509. #define    IO_SUCCESS    (SS$_NORMAL | STS$M_INHIB_MSG)
  510. #define    IO_ERROR    SS$_ABORT
  511. #endif
  512. /*
  513.  * Note: IO_SUCCESS and IO_ERROR are defined in the Decus C stdio.h file
  514.  */
  515. #ifndef    IO_SUCCESS
  516. #define    IO_SUCCESS    0
  517. #endif
  518. #ifndef    IO_ERROR
  519. #define    IO_ERROR    1
  520. #endif
  521.  
  522. #define EOS        0
  523. #define    FALSE        0
  524. #define    TRUE        1
  525.  
  526. /*
  527.  * The following status codes are returned by gethdr()
  528.  */
  529. #define DONE    0
  530. #define    GOTCHA    1
  531. #define    NOGOOD    2
  532.  
  533. char        text[513];        /* Working text line        */
  534. char        name[81];        /* Current archive member name    */
  535. char        filename[81];        /* Working file name        */
  536. char        arfilename[81];        /* Archive file name        */
  537. char        fullname[81];        /* Output for argetname()    */
  538. int        verbose        = TRUE;    /* TRUE for verbosity        */
  539. int        first_archive;        /* For mail header skipping    */
  540.  
  541. main(argc, argv)
  542. int        argc;            /* Arg count            */
  543. char        *argv[];        /* Arg vector            */
  544. {
  545.     register int        i;    /* Random counter        */
  546.     int            status;    /* Exit status            */
  547.  
  548. #ifdef    vms
  549.     argc = getredirection(argc, argv);
  550. #endif
  551.     status = IO_SUCCESS;
  552.     if (argc == 1)
  553.         process();
  554.     else {
  555.         for (i = 1; i < argc; i++) {
  556.         if (freopen(argv[i], "r", stdin) != NULL)
  557.             process();
  558.         else {
  559.             perror(argv[i]);
  560.             status = IO_ERROR;
  561.         }
  562.         }
  563.     }
  564.     exit(status);
  565. }
  566.  
  567. process()
  568. /*
  569.  * Process archive open on stdin
  570.  */
  571. {
  572.     register char        *fn;    /* File name pointer        */
  573.     register FILE        *outfd;
  574.     register int        i;
  575.  
  576.     text[0] = EOS;
  577.     while ((i = gethdr()) != DONE) {
  578.         switch (i) {
  579.         case GOTCHA:
  580.         if ((outfd = fopen(name, "w")) == NULL) {
  581.             perror(name);
  582.             fprintf(stderr, "Can't create \"%s\"\n", name);
  583.             arskip();
  584.             continue;
  585.         }
  586.         break;
  587.  
  588.         case NOGOOD:
  589.         fprintf(stderr, "Missing -h-, writing to archx.tmp\n");
  590.         fprintf(stderr, "Current text line: %s", text);
  591.         strcpy(name, "archx.tmp");
  592.         if ((outfd = fopen(name, "a")) == NULL) {
  593.             perror(name);
  594.             fprintf(stderr, "Cannot append to %s\n", name);
  595.             arskip();
  596.             continue;
  597.         }
  598.         break;
  599.         }
  600.         arexport(outfd);
  601.         fclose(outfd);
  602.     }
  603. }
  604.  
  605. int
  606. gethdr()
  607. /*
  608.  * If text is null, read a record, returning to signal input state:
  609.  *    DONE    Eof read
  610.  *    NOGOOD    -h- wasn't first non-blank line.  Line is in text[]
  611.  *    GOTCHA    -h- found, parsed into name.
  612.  */
  613. {
  614.     register char    *tp;
  615.     register char    *np;
  616.  
  617. again:    if (text[0] == EOS
  618.      && fgets(text, sizeof text, stdin) == NULL)
  619.         return (DONE);
  620.     if (text[0] == '\n' && text[1] == EOS) {
  621.         text[0] = EOS;
  622.         goto again;
  623.     }
  624.     if (text[0] != '-'
  625.      || text[1] != 'h'
  626.      || text[2] != '-')
  627.         return (NOGOOD);
  628.     for (tp = &text[3]; isspace(*tp); tp++)
  629.         ;
  630.     for (np = name; !isspace(*tp); *np++ = *tp++)
  631.         ;
  632.     *np = EOS;
  633.     return (GOTCHA);
  634. }
  635.  
  636. arskip()
  637. /*
  638.  * Skip to next header
  639.  */
  640. {
  641.     while (fgets(text, sizeof text, stdin) != NULL) {
  642.         if (text[0] == '-' && text[1] == 'h' && text[2] == '-')
  643.         return;
  644.     }
  645.     text[0] = EOS;                /* EOF signal        */
  646. }
  647.  
  648. arexport(outfd)
  649. register FILE    *outfd;
  650. /*
  651.  * Read secret archive format, writing archived data to outfd.
  652.  * Clean out extraneous <cr>,<lf>'s
  653.  */
  654. {
  655.     register char    *tp;
  656.     unsigned int    nrecords;
  657.  
  658.     printf("Creating \"%s\", ", name);
  659.     nrecords = 0;
  660.     while (fgets(text, sizeof text, stdin) != NULL) {
  661.         tp = &text[strlen(text)];
  662.         if (tp > &text[1] && *--tp == '\n' && *--tp == '\r') {
  663.         *tp++ = '\n';
  664.         *tp = EOS;
  665.         }
  666.         if (text[0] == '-') {
  667.         if (text[1] == 'h')
  668.             goto gotcha;
  669.         fputs(text+1, outfd);
  670.         }
  671.         else {
  672.         fputs(text, outfd);
  673.         }
  674.         nrecords++;
  675.     }
  676.     text[0] = EOS;
  677. gotcha:    printf("%u records\n", nrecords);
  678.     if (ferror(stdin) || ferror(outfd))
  679.         printf("Creation of \"%s\" completed with error\n", name);
  680. }
  681.  
  682. /*
  683.  * getredirection() is intended to aid in porting C programs
  684.  * to VMS (Vax-11 C) which does not support '>' and '<'
  685.  * I/O redirection.  With suitable modification, it may
  686.  * useful for other portability problems as well.
  687.  */
  688.  
  689. #ifdef    vms
  690. static int
  691. getredirection(argc, argv)
  692. int        argc;
  693. char        **argv;
  694. /*
  695.  * Process vms redirection arg's.  Exit if any error is seen.
  696.  * If getredirection() processes an argument, it is erased
  697.  * from the vector.  getredirection() returns a new argc value.
  698.  *
  699.  * Warning: do not try to simplify the code for vms.  The code
  700.  * presupposes that getredirection() is called before any data is
  701.  * read from stdin or written to stdout.
  702.  *
  703.  * Normal usage is as follows:
  704.  *
  705.  *    main(argc, argv)
  706.  *    int        argc;
  707.  *    char        *argv[];
  708.  *    {
  709.  *        argc = getredirection(argc, argv);
  710.  *    }
  711.  */
  712. {
  713.     register char        *ap;    /* Argument pointer    */
  714.     int            i;    /* argv[] index        */
  715.     int            j;    /* Output index        */
  716.     int            file;    /* File_descriptor     */
  717.  
  718.     for (j = i = 1; i < argc; i++) {   /* Do all arguments    */
  719.         switch (*(ap = argv[i])) {
  720.         case '<':            /* <file        */
  721.         if (freopen(++ap, "r", stdin) == NULL) {
  722.             perror(ap);        /* Can't find file    */
  723.             exit(IO_ERROR);    /* Is a fatal error    */
  724.         }
  725.  
  726.         case '>':            /* >file or >>file    */
  727.         if (*++ap == '>') {    /* >>file        */
  728.             /*
  729.              * If the file exists, and is writable by us,
  730.              * call freopen to append to the file (using the
  731.              * file's current attributes).  Otherwise, create
  732.              * a new file with "vanilla" attributes as if
  733.              * the argument was given as ">filename".
  734.              * access(name, 2) is TRUE if we can write on
  735.              * the specified file.
  736.              */
  737.             if (access(++ap, 2) == 0) {
  738.             if (freopen(ap, "a", stdout) != NULL)
  739.                 break;    /* Exit case statement    */
  740.             perror(ap);    /* Error, can't append    */
  741.             exit(IO_ERROR);    /* After access test    */
  742.             }            /* If file accessable    */
  743.         }
  744.         /*
  745.          * On vms, we want to create the file using "standard"
  746.          * record attributes.  create(...) creates the file
  747.          * using the caller's default protection mask and
  748.          * "variable length, implied carriage return"
  749.          * attributes. dup2() associates the file with stdout.
  750.          */
  751.         if ((file = creat(ap, 0, "rat=cr", "rfm=var")) == -1
  752.          || dup2(file, fileno(stdout)) == -1) {
  753.             perror(ap);        /* Can't create file    */
  754.             exit(IO_ERROR);    /* is a fatal error    */
  755.         }            /* If '>' creation    */
  756.         break;            /* Exit case test    */
  757.  
  758.         default:
  759.         argv[j++] = ap;        /* Not a redirector    */
  760.         break;            /* Exit case test    */
  761.         }
  762.     }                /* For all arguments    */
  763.     return (j);
  764. }
  765. #endif
  766.  
  767. SHAR_EOF
  768. if test 7837 -ne "`wc -c < 'archx.c'`"
  769. then
  770.     echo shar: error transmitting "'archx.c'" '(should have been 7837 characters)'
  771. fi
  772. fi
  773. exit 0
  774. #    End of shell archive
  775.